/*
 * Copyright (C) 2008 Matt Falkoski
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.falko.android.raven.animator;

import java.util.Random;

import com.falko.android.raven.R;
import com.falko.android.raven.renderer.Texture;
import com.falko.android.raven.renderer.TextureLibrary;
import com.falko.android.raven.util.AndroidUtil;

public class AnimationFactory {

	@SuppressWarnings("unused")
	private final String TAG = getClass().getName();
	private static final int DEFAULT_QUEUE_LENGTH = 10;
	private Random rand_ = new Random(System.currentTimeMillis());

	// AnimationFactory variables
	private AnimationQueue animationQueue_;
	private TextureLibrary textureLibrary_ = null;
	int[] textureIDs_;
	private int width_ = 50;
	private int height_ = 50;

	// Animation Logic
	private SpriteExplosion spriteExplosionLogic_ = null;

	// user settings for sprite explosion
	private int textureIndex_;
	
	// count settings
	private boolean randomCount_ = false;
	private int spriteCount_;
	private int minCount_;
	private int maxCount_;
	
	// size settings
	private boolean randomSize_ = false;
	private int sizeScale_;
	private int minSizeScale_;
	private int maxSizeScale_;
	private int velocity_;
	private String gravityMode_;
	
	public enum AnimationType {
		SPRITE_EXPLOSION, SHIP
	}

	public AnimationFactory() {
		this(DEFAULT_QUEUE_LENGTH);
	}

	public AnimationFactory(int size) {
		textureLibrary_ = new TextureLibrary();
		spriteExplosionLogic_ = new SpriteExplosion();
		initFactoryQueue(size);
		loadTextures();
	}

	private void initFactoryQueue(int size) {
		animationQueue_ = new AnimationQueue(size);
		for (int i = 0; i < size; ++i) {
			animationQueue_.putAnimation(new Animation());
		}
	}

	private void loadTextures() {
		textureIDs_ = AndroidUtil.getAllResourceIDs(R.drawable.class);
		for (int i = 0; i < textureIDs_.length; ++i) {
			textureLibrary_.allocateTexture(textureIDs_[i]);
		}
	}

	public void setSpriteScale(long data) {
		randomSize_ = ((data >>> 24) & 0x1) == 1;
		sizeScale_ = (int) ((data >>> 16) & 0xFF);
		maxSizeScale_ = (int) ((data >>> 8) & 0xFF);
		minSizeScale_ = (int) (data & 0xFF);
	}

	public void setSpriteTexture(int index) {
		textureIndex_ = index;
	}

	public void setSpriteCount(long data) {
		randomCount_ = ((data >>> 24) & 0x1) == 1;
		spriteCount_ = (int) ((data >>> 16) & 0xFF);
		maxCount_ = (int) ((data >>> 8) & 0xFF);
		minCount_ = (int) (data & 0xFF);
	}

	public AnimationQueue getAnimationQueue() {
		return animationQueue_;
	}

	public TextureLibrary getTextureLibrary() {
		return textureLibrary_;
	}

	public void setDimentions(int width, int height) {
		width_ = width;
		height_ = height;
	}

	public void recycle(Animation a) {
		a.onRecycle();
		animationQueue_.putAnimation(a);
	}

	public Animation getAnimation(AnimationType type, float x, float y) {

		if (animationQueue_.size() == 0)
			return null;

		Animation retAnimation = animationQueue_.take();

		switch (type) {

		case SPRITE_EXPLOSION:
			initSpriteExplosion(retAnimation, x, y);
			break;

		case SHIP: // Extension for next app
			break; // not used
		}

		return retAnimation;
	}

	private void initSpriteExplosion(Animation a, float x, float y) {

		int count = 0;
		if (randomCount_) {
			count = rand_.nextInt(maxCount_ - minCount_) + minCount_;
		} else {
			count = spriteCount_;
		}

		a.putInt(SpriteExplosion.SPRITE_COUNT, count);
		Texture t = textureLibrary_
				.getTextureByResource(textureIDs_[textureIndex_]);
		a.putTexture(SpriteExplosion.SPRITE_TEXTURE, t);
		a.putFloat(SpriteExplosion.X_LOC, x);
		a.putFloat(SpriteExplosion.Y_LOC, height_ - y);
		a.putInt(SpriteExplosion.WIDTH, width_);
		a.putInt(SpriteExplosion.HEIGHT, height_);
		a.putInt(SpriteExplosion.SPRITE_SCALE, sizeScale_);
		a.putInt(SpriteExplosion.MIN_SPRITE_SCALE, minSizeScale_);
		a.putInt(SpriteExplosion.MAX_SPRITE_SCALE, maxSizeScale_);
		a.putBool(SpriteExplosion.RAND_SPRITE_SCALE, randomSize_);
		a.putString(SpriteExplosion.MODE, gravityMode_);
		a.putInt(SpriteExplosion.VELOCITY, velocity_);
		a.bindLogic(spriteExplosionLogic_);
	}

	public void setGravityMode(String string) {
		gravityMode_ = string;
	}

	public void setVelocity(int vel) {
		velocity_ = vel * 280;
	}
}
